package util

import (
	"fmt"
	"go/format"
	"os"
	"path/filepath"
	"strings"

	"golang.org/x/tools/imports"
)

// Create Creates or truncates the named file,if the file path contains directories, it will make them first.
func Create(file string) (*os.File, error) {
	if !FileExists(file) {
		if i := strings.LastIndex(file, "/"); i != -1 {
			if err := os.MkdirAll(file[:i], 0755); err != nil {
				return nil, err
			}
		}
	}
	return os.Create(file)
}

// FileExists checks whether a file exists.
func FileExists(file string) bool {
	if _, err := os.Stat(file); os.IsNotExist(err) {
		return false
	}
	return true
}

// FormatGoCode 格式化go代码
func FormatGoCode(file string) error {
	c, err := os.ReadFile(file)
	if err != nil {
		return err
	}
	c, err = format.Source(c)
	if err != nil {
		return err
	}
	c, err = imports.Process(file, c, nil)
	if err != nil {
		return err
	}
	return os.WriteFile(file, c, 0666)
}

// FileExistsOrCreate 文件是否存在，不存递归创建文件夹
func FileExistsOrCreate(dir string) error {
	exi := FileExists(dir)
	if !exi {
		// 创建文件夹
		return os.MkdirAll(dir, os.ModePerm)
	}

	return nil
}

// DirExists 检查目录是否存在
func DirExists(path string) bool {
	info, err := os.Stat(path)
	if err != nil {
		if os.IsNotExist(err) {
			return false
		}
		// 其他错误（如权限问题）也认为目录不可用
		return false
	}
	return info.IsDir()
}

// DirExistsOrCreate 检查目录是否存在，不存在则创建
func DirExistsOrCreate(path string) error {
	// 使用 os.Stat 判断目录是否存在
	_, err := os.Stat(path)
	if err == nil {
		// 目录存在
		return nil
	}

	// 如果错误是因为目录不存在，则创建目录
	if os.IsNotExist(err) {
		// 使用 os.MkdirAll 创建目录（包括必要的父目录）
		err = os.MkdirAll(path, os.ModePerm)
		if err != nil {
			return fmt.Errorf("%s %+v", path, err)
		}
	}

	return nil
}

// GetDirs 获取文件夹下所有文件夹路径
func GetDirs(dirPath string) (dirs []string, err error) {
	err = filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if info.IsDir() {
			dirs = append(dirs, path)
		}
		return nil
	})
	if err != nil {
		fmt.Println("GetDirs Error :", err)
	}
	return
}

// GetProtoFiles 获取所有proto文件路径
func GetProtoFiles(dirPath string) ([]string, error) {
	dirs, err := GetDirs(dirPath)
	if err != nil {
		return nil, err
	}
	var files []string
	for _, dir := range dirs {
		fs, fErr := filepath.Glob(dir + "/*.proto")
		if fErr != nil {
			return nil, fErr
		}
		files = append(files, fs...)
	}

	return files, nil
}

// GetPbFiles 获取所有pb文件路径
func GetPbFiles(dirPath string) ([]string, error) {
	dirs, err := GetDirs(dirPath)
	if err != nil {
		return nil, err
	}
	var files []string
	for _, dir := range dirs {
		fs, fErr := filepath.Glob(dir + "/*.pb.go")
		if fErr != nil {
			return nil, fErr
		}
		files = append(files, fs...)
	}

	return files, nil
}
